from enum import Enum, auto

class TokenType(Enum):
    # Keywords
    USING = auto()
    CLASS = auto()
    DEF = auto()
    PRINT = auto()
    PRINTIN = auto()
    TRUE = auto()
    FALSE = auto()
    IF = auto()
    ELSE = auto()
    INPUTON = auto()
    READFILE = auto()
    WRITEFILE = auto()
    
    # Identifiers
    IDENTIFIER = auto()
    
    # Literals
    NUMBER = auto()
    STRING = auto()
    
    # Operators
    EQUAL = auto()
    PLUS = auto()
    MINUS = auto()
    EQ = auto()      # ==
    NE = auto()      # !=
    LT = auto()      # <
    GT = auto()      # >
    LTE = auto()     # <=
    GTE = auto()     # >=
    
    # Delimiters
    LPAREN = auto()
    RPAREN = auto()
    LBRACE = auto()
    RBRACE = auto()
    SEMICOLON = auto()
    DOT = auto()
    COMMA = auto()
    
    # EOF
    EOF = auto()

class Token:
    def __init__(self, type, value=None):
        self.type = type
        self.value = value
        
    def __repr__(self):
        return f"Token({self.type}, {self.value})"

class Lexer:
    def __init__(self, text):
        self.text = text
        self.pos = 0
        self.current_char = self.text[self.pos] if self.text else None
        
    def advance(self):
        self.pos += 1
        if self.pos >= len(self.text):
            self.current_char = None
        else:
            self.current_char = self.text[self.pos]
            
    def skip_whitespace(self):
        while self.current_char is not None and self.current_char.isspace():
            self.advance()
            
    def identifier(self):
        result = ""
        while self.current_char is not None and (self.current_char.isalnum() or self.current_char == "_"):
            result += self.current_char
            self.advance()
            
        # Check if it's a keyword
        if result == "using":
            return Token(TokenType.USING)
        elif result == "class":
            return Token(TokenType.CLASS)
        elif result == "def":
            return Token(TokenType.DEF)
        elif result == "print":
            return Token(TokenType.PRINT)
        elif result == "printIn":
            return Token(TokenType.PRINTIN)
        elif result == "true":
            return Token(TokenType.TRUE, True)
        elif result == "false":
            return Token(TokenType.FALSE, False)
        elif result == "if":
            return Token(TokenType.IF)
        elif result == "else":
            return Token(TokenType.ELSE)
        elif result == "inputOn":
                return Token(TokenType.INPUTON)
        elif result == "readFile":
            return Token(TokenType.READFILE)
        elif result == "writeFile":
            return Token(TokenType.WRITEFILE)
        else:
            return Token(TokenType.IDENTIFIER, result)
            
    def number(self):
        result = ""
        while self.current_char is not None and self.current_char.isdigit():
            result += self.current_char
            self.advance()
        return Token(TokenType.NUMBER, int(result))
        
    def string(self):
        self.advance()  # Skip opening quote
        result = ""
        while self.current_char is not None and self.current_char != '"':
            result += self.current_char
            self.advance()
        self.advance()  # Skip closing quote
        return Token(TokenType.STRING, result)
        
    def get_next_token(self):
        while self.current_char is not None:
            if self.current_char.isspace():
                self.skip_whitespace()
                continue
                
            if self.current_char.isalpha() or self.current_char == "_":
                return self.identifier()
                
            if self.current_char.isdigit():
                return self.number()
                
            if self.current_char == '"':
                return self.string()
                
            # Multi-character operators
            if self.current_char == "=":
                self.advance()
                if self.current_char == "=":
                    self.advance()
                    return Token(TokenType.EQ)
                return Token(TokenType.EQUAL)
                
            if self.current_char == "!":
                self.advance()
                if self.current_char == "=":
                    self.advance()
                    return Token(TokenType.NE)
                raise Exception("Invalid token '!' - did you mean '!='?")
                
            if self.current_char == "<":
                self.advance()
                if self.current_char == "=":
                    self.advance()
                    return Token(TokenType.LTE)
                return Token(TokenType.LT)
                
            if self.current_char == ">":
                self.advance()
                if self.current_char == "=":
                    self.advance()
                    return Token(TokenType.GTE)
                return Token(TokenType.GT)
                
            if self.current_char == "+":
                self.advance()
                return Token(TokenType.PLUS)
                
            if self.current_char == "-":
                self.advance()
                return Token(TokenType.MINUS)
                
            if self.current_char == "(":
                self.advance()
                return Token(TokenType.LPAREN)
                
            if self.current_char == ")":
                self.advance()
                return Token(TokenType.RPAREN)
                
            if self.current_char == "{":
                self.advance()
                return Token(TokenType.LBRACE)
                
            if self.current_char == "}":
                self.advance()
                return Token(TokenType.RBRACE)
                
            if self.current_char == ";":
                self.advance()
                return Token(TokenType.SEMICOLON)
                
            if self.current_char == ".":
                self.advance()
                return Token(TokenType.DOT)
                
            if self.current_char == ",":
                self.advance()
                return Token(TokenType.COMMA)
                
            if self.current_char == "#":
                # Skip comment until end of line
                while self.current_char is not None and self.current_char != "\n":
                    self.advance()
                continue
                
            raise Exception(f"Invalid character: {self.current_char}")
            
        return Token(TokenType.EOF)
